package cn.birdbaby.plugins.sync;

import cn.birdbaby.plugins.annotator.Context;
import cn.birdbaby.plugins.annotator.classannotator.gen.BBProcessingAddGenAnnotationsTask;
import cn.birdbaby.plugins.annotator.fieldannotator.fielddesc.FieldDescAnnotator;
import cn.birdbaby.plugins.common.CommonUtils;
import com.intellij.codeInsight.actions.LayoutCodeOptions;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileSet;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;

/**
 * @author llorando 4/8/24 9:40 am
 */
public class BBSyncProcessor {
    private DataContext dataContext;
    private Project project;
    private Editor editor;
    private Document document;

    private PsiFile psiFile;
    private List<PsiFile> psiFiles;
    private LayoutCodeOptions options;
    private List<PsiAnnotation> genAnnotations;

    //默认生成全部注解

    public BBSyncProcessor(Project project, Editor editor, PsiFile psiFile) {
        this.psiFile = psiFile;
        this.project = project;
        this.editor = editor;
        this.genAnnotations = new ArrayList<>();
    }

    public BBSyncProcessor(Project project, Editor editor, List<PsiFile> files) {
        this.psiFiles = files;
        this.project = project;
        this.editor = editor;
        this.genAnnotations = new ArrayList<>();

    }

    public void processCode() {
        if (!Objects.isNull(psiFile)) {
            processSingleFile();
        } else {
            processFiles();
        }
    }

    //在递归的过程中进行处理
    void processAll(Project myProject, VirtualFile[] myRoots, Function<PsiElement, Boolean> checker, Collection<PsiElement> container) {
        VirtualFileSet visited = VfsUtilCore.createCompactVirtualFileSet();
        for (VirtualFile root : myRoots) {
            //逐个访问root【file、dir、dir or file in dir】中的元素
            boolean success = ProjectRootManager.getInstance(myProject).getFileIndex().iterateContentUnderDirectory(root, fileOrDir -> {
                //如果当前访问的虚拟文件是dir，并且已经存在访问记录了，直接返回
                if (fileOrDir.isDirectory() || !visited.add(fileOrDir)) {
                    return true;
                }
                PsiFile psiFile = ReadAction.compute(() -> myProject.isDisposed() ? null : PsiManager.getInstance(myProject).findFile(fileOrDir));
                //断路器
                if (psiFile == null || checker.apply(psiFile)) container.add(psiFile);
                return false;
            });
        }
    }

    public void processSingleFile() {
        //默认给当前文件中的所有属性都添加FieldDesc字段
        if (!CommonUtils.isEntity(psiFile)) throw new RuntimeException("不是entity文件不给加.避免批次操作的时候误伤");
        PsiClass psiClass = PsiTreeUtil.findChildOfType(psiFile, PsiClass.class);
        PsiField[] fields = psiClass.getFields();
        for (PsiField field : fields) {
            FieldDescAnnotator annotator = new FieldDescAnnotator();
            if (annotator.support(field)) {
                Context context = new Context(psiFile);
                context.setCurrentElement(field);
                annotator.buildPsiAnnotation(context);
            }
        }
//        String groupId=UUID.randomUUID().toString();
//        CommonUtils.processWithGroupId(project,groupId,() ->
//                new AnnotatorProcessor(psiFile, groupId, Constants.all).addGenAnnotation()
//        );
//        PsiDocumentManager.getInstance(project).commitDocument(document);

    }

    public void processFiles() {
        boolean isSuccess = ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> {
            ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
            return processFilesUnderProgress(indicator);
        }, "bb add gen", true, project);

        //如果当前编辑器中存在打开的文件，更新一下
        if (editor != null) {
            CodeStyleSettingsManager.getInstance(project).notifyCodeStyleSettingsChanged();
        }
    }

    public boolean processFilesUnderProgress(@NotNull ProgressIndicator indicator) {
        indicator.setIndeterminate(false);
        BBProcessingAddGenAnnotationsTask processor = new BBProcessingAddGenAnnotationsTask(indicator, project, editor);
        processor.process();
        return true;
    }


}
